local _ENV,_START = hf_setenv('activity_mgr',true)

local skynet     = require "skynet.manager"
local constant   = require "constant"
local util       = require "util"
local utils      = require "utils"
local reason     = require "reason"
local game_def   = require "game_def"
local sharedata  = require "skynet.sharedata"

local table_insert = table.insert

local CMD = {}
function init()
    global_configs = nil
    activity_service_map = {}
    gm_time = 0

    hf_set_sentinel_end(_ENV)
end

local function on_activity_start(act_id,conf)
    local service_conf = game_def.ACIVITY_SERVICE_MAP[conf.ac_type]
    if not service_conf then
        return
    end

    local service_name = service_conf.act_service_name
    local service_addr = skynet.newservice(service_name)
    skynet.name("." .. service_name,service_addr)

    local act_end_time = utils.get_time_by_string(conf.ac_end_time)
    local preload = {act_id = act_id,service_name = service_name,act_end_time = act_end_time}
    skynet.call(service_addr,"lua", "start", preload)

    activity_service_map[act_id] = service_addr

    R().hallsvr():broadcast('.msg_handler', 'on_activity_start',{act_id = act_id,act_type = conf.ac_type})
end

local function on_activity_end(act_id,conf,is_temp_close)
    local service_addr = activity_service_map[act_id]
    if not service_addr then
        return
    end
    local ok = skynet.call(service_addr,"lua","on_activity_end",is_temp_close)
    if not ok then
        errlog("on_activity_end=====error",act_id)
        return
    end
    activity_service_map[act_id] = nil
    R().hallsvr():broadcast('.msg_handler', 'on_activity_end',{act_id = act_id,act_type = conf.ac_type})
end

function get_activity_time()
    return gm_time + util.get_now_time()
end

function do_check_open_and_close()
    local now = get_activity_time()

    local activities = global_configs.activity
    for act_id,activity in pairs(activities) do
        print("act_id==========",act_id,activity.ac_begin_time,type(activity.ac_begin_time))
        local begin_time = utils.get_time_by_string(activity.ac_begin_time)
        local end_time   = utils.get_time_by_string(activity.ac_end_time)
        
        --检查活动开始
        if (now >= begin_time and now <= end_time) and not activity_service_map[act_id] and activity.open_state then
            on_activity_start(act_id,activity)
        end

        if (now >= begin_time and now <= end_time) and activity_service_map[act_id] and not activity.open_state then
            on_activity_end(act_id,activity,true)
        end

        --检查活动结束
        if (now > end_time) and activity_service_map[act_id] then
            on_activity_end(act_id,activity)
        end
    end
end

local function check_activity_open_and_close()
	while true do
        local ok, ret = xpcall(do_check_open_and_close, debug.traceback)
        if not ok then
            errlog(ret)
        end

		skynet.sleep(1000)
	end
end

local function cal_player_task_status(uid,data,activity)
    local ret_data = {}
    for _,task in pairs(activity.ac_content.task_list) do
        local target_list = utils.str_split(task.task_target,';')
        local award_list  = utils.str_split(task.task_awards,';')

        local cur_process = 0
        if task.task_type == game_def.ACT_TASK_PLAY_COUNT then
            cur_process = data.play_times or 0
        elseif task.task_type == game_def.ACT_TASK_LOGIN_DAY then
            cur_process = data.login_day_count or 0
        elseif task.task_type == game_def.ACT_TASK_ONLINE_TIME then
            local ok,continue_time = R().hallsvr({key=uid}):call('.msg_handler', 'get_today_continue_time',uid)
            print("get_continue_time==========",uid,ok,continue_time)
            cur_process = (data.day_online_time or 0) + continue_time
        end

        for k,v in pairs(target_list) do
            local target = tonumber(v)
            local one_task = {}
            one_task.task_type = task.task_type
            one_task.task_index = k
            one_task.task_desc = task.task_desc
            one_task.cur_process = cur_process <= target and cur_process or target
            one_task.target_process = target
            one_task.award_coins = tonumber(award_list[k] or 0)

            local bt_status = cur_process >= target and 1 or 0 --1可领取 0不可领取
            if task.task_type == game_def.ACT_TASK_PLAY_COUNT then
                bt_status = (data.play_times_map or {})[tostring(target)] and 2 or bt_status  --2是已经领取
            elseif task.task_type == game_def.ACT_TASK_LOGIN_DAY then
                bt_status = (data.login_day_map or {})[tostring(target)] and 2 or bt_status   --2是已经领取
            elseif task.task_type == game_def.ACT_TASK_ONLINE_TIME then
                bt_status = (data.online_time_map or {})[tostring(target)] and 2 or bt_status --2是已经领取
            end
            one_task.bt_status = bt_status

            table_insert(ret_data,one_task)
        end
    end

    return ret_data
end

local function cal_player_charge_status(uid,data,activity)
    print_r("cal_player_charge_status",tostring_r(activity))
    local ret_data = {}
    ret_data.charge_state = data.charge_state
    ret_data.cur_process = math.min(data.cur_process or 0,activity.ac_content.earn_coins)
    ret_data.target_process = activity.ac_content.earn_coins
    ret_data.award_coins = activity.ac_content.back_coins

    ret_data.bt_status = ret_data.cur_process >= ret_data.target_process and 1 or 0 --1可领取 0不可领取
    if data.take_status == game_def.first_charge_has_taken then
        ret_data.bt_status = 2  --已领取
    end

    return ret_data
end

------------------通用begin-----------------------
local function check_player_first_charge(uid)
    local ok,frist_charge_status = R().basesvr({key=uid}):call('.msg_handler','check_player_first_charge',uid)
    if not ok then
        errlog('check_player_first_charge failed',uid)
        return false
    end

    return frist_charge_status
end

function CMD.get_activity_list(uid)
    print("get_activity_list========aa",uid)
	local now = get_activity_time()
    local activity_list = {}
    local activities = global_configs.activity
	for act_id,activity in pairs(activities) do
		if not activity.open_state then
			goto continue
		end

        if activity.ac_type == game_def.ACTIVITY_TYPE_FIRST_CAHRGE and 
        not check_player_first_charge(uid) then
            print("get_activity_list========bb")
            goto continue
        end

        print("get_activity_list===========11",act_id,activity.ac_begin_time,activity.ac_end_time)
        local act_begin_time = utils.get_time_by_string(activity.ac_begin_time)
        local act_end_time = utils.get_time_by_string(activity.ac_end_time)
        if act_begin_time > now then --未开始
            goto continue
        end
        if act_end_time <= now then --已经结束
            goto continue
        end

        local act_data = {}
		local activity_common = {
			act_id   = act_id,
			act_type = activity.ac_type,
			act_begin_time = utils.get_time_by_string(activity.ac_begin_time),
			act_end_time   = utils.get_time_by_string(activity.ac_end_time),
			open_state = activity.open_state,
            bg_url = activity.ac_content.bg_url,
            act_name = activity.ac_name,
            act_desc = activity.ac_content.ac_desc,
		}
        act_data.activity_common = activity_common
        print("get_activity_list===========22",act_id,activity.ac_begin_time,activity.ac_end_time)
        if activity.ac_type == game_def.ACTIVITY_TYPE_JUMP_PICTURE then
            local data = {
                jump_position = activity.ac_content.jump_position,
                jump_bt_url = activity.ac_content.jump_bt_url,
                jump_bt_position = activity.ac_content.jump_bt_position
            }
            act_data.jump_module = data
        elseif activity.ac_type == game_def.ACTIVITY_TYPE_JUMP_WEB then
            local data = {
                web_url = activity.ac_content.web_url,
                jump_bt_url = activity.ac_content.jump_bt_url,
                jump_bt_position = activity.ac_content.jump_bt_position
            }
            act_data.jump_web = data
        elseif activity.ac_type == game_def.ACTIVITY_TYPE_TASK then
            local service_addr = activity_service_map[act_id]
            if service_addr then
                local ret_data = skynet.call(service_addr,"lua", "get_player_activity_data",uid)
                print("get_player_activity_data=====11",tostring_r(ret_data))
                if ret_data then
                    act_data.task_activity = {}
                    act_data.task_activity.target_list = cal_player_task_status(uid,ret_data,activity)
                end
            end
        elseif activity.ac_type == game_def.ACTIVITY_TYPE_FIRST_CAHRGE then
            local service_addr = activity_service_map[act_id]
            if service_addr then
                local ret_data = skynet.call(service_addr,"lua", "get_player_activity_data",uid)
                print("get_player_activity_data=====",tostring_r(ret_data),tostring_r(activity))
                if ret_data then
                    act_data.charge_activity = cal_player_charge_status(uid,ret_data,activity)
                else
                    act_data.charge_activity = {
                        charge_state = 2,
                        cur_process = 0,
                        target_process = activity.ac_content.charge_target,
                        award_coins = activity.ac_content.back_coins,
                        bt_status = 0,
                    }
                end
                activity_common.show_icon = true
            end
        elseif activity.ac_type == game_def.ACTIVITY_TYPE_RANK then
            local service_addr = activity_service_map[act_id]
            if service_addr then
                local ret_data = skynet.call(service_addr,"lua", "get_player_activity_data",uid)
                print("get_player_activity_data=====22",tostring_r(ret_data))
                if ret_data then
                    act_data.rank_activity = {}
                    act_data.rank_activity.rank = ret_data.rank
                    act_data.rank_activity.today_coins = ret_data.value
                end
            end
        end

        if activity.ac_type == game_def.ACTIVITY_TYPE_BIND_PHONE then
            local ok,can_take = R().hallsvr{key=uid}:call('.msg_handler','callagent',uid,'can_take_bind_phone_award')
            print("can_take_bind_phone_award============",ok,can_take)
            if not ok or not can_take then
                goto continue
            end

            local data = {
                jump_bt_url = activity.ac_content.jump_bt_url,
                jump_bt_position = activity.ac_content.jump_bt_position
            }
            act_data.bind_phone_activity = data
        end

        print("get_activity_list===========33",tostring_r(act_data))
        table_insert(activity_list,act_data)

		::continue::
	end

    print("get_activity_list============end",tostring_r(activity_list))
	return skynet.retpack(activity_list)
end

function CMD.get_task_act_data(uid,act_id)
    local activity = global_configs.activity[act_id]
    if not activity or not activity.open_state then
        return skynet.retpack(false)
    end
    local service_addr = activity_service_map[act_id]
    if not service_addr then
        return skynet.retpack(false)
    end
   
    local ret_data = skynet.call(service_addr,"lua", "get_player_activity_data",uid)
    if not ret_data then
        return skynet.retpack(false)
    end

    local ret_data = cal_player_task_status(uid,ret_data,activity)
    return skynet.retpack(ret_data)
end

---------------------通用end---------------------------
--增加活动玩牌次数
function CMD.add_act_play_count(uid,count)
    local activities = global_configs.activity
    for act_id,activity in pairs(activities) do
        local service_addr = activity_service_map[act_id]
        if not service_addr then
            goto continue
        end

        if activity.ac_type ~= game_def.ACTIVITY_TYPE_TASK then --不是任务型活动
            goto continue
        end

        if not activity.ac_content.task_list then
            goto continue
        end

        local have_play_count_task = false
        for _,task in pairs(activity.ac_content.task_list) do
            if task.task_type == game_def.ACT_TASK_PLAY_COUNT then
                have_play_count_task = true
            end
        end
        if not have_play_count_task then
            goto continue
        end

        skynet.send(service_addr,"lua", "add_act_play_count",uid,count)

        ::continue::
    end
end

--增加活动登录天数
function CMD.act_add_login_day(uid,count)
    print("act_add_login_day============",uid,count)
    local activities = global_configs.activity
    for act_id,activity in pairs(activities) do
        local service_addr = activity_service_map[act_id]
        if not service_addr then
            goto continue
        end

        if activity.ac_type ~= game_def.ACTIVITY_TYPE_TASK then --不是任务型活动
            goto continue
        end

        if not activity.ac_content.task_list then
            goto continue
        end

        local have_login_day_task = false
        for _,task in pairs(activity.ac_content.task_list) do
            if task.task_type == game_def.ACT_TASK_LOGIN_DAY then
                have_login_day_task = true
            end
        end
        if not have_login_day_task then
            goto continue
        end

        skynet.send(service_addr,"lua", "act_add_login_day",uid,count)

        ::continue::
    end
end

--增加每天在线时长
function CMD.act_add_day_online_time(uid,online_seconds)
    local activities = global_configs.activity
    for act_id,activity in pairs(activities) do
        local service_addr = activity_service_map[act_id]
        if not service_addr then
            goto continue
        end

        if activity.ac_type ~= game_def.ACTIVITY_TYPE_TASK then --不是任务型活动
            goto continue
        end

        if not activity.ac_content.task_list then
            goto continue
        end

        local have_online_time_task = false
        for _,task in pairs(activity.ac_content.task_list) do
            if task.task_type == game_def.ACT_TASK_ONLINE_TIME then
                have_online_time_task = true
            end
        end
        if not have_online_time_task then
            goto continue
        end
        
        skynet.send(service_addr,"lua", "act_add_day_online_time",uid,online_seconds)

        ::continue::
    end
end

function CMD.take_task_act_award(uid,act_id,task_type,target_process)
    local activity = global_configs.activity[act_id]
    if not activity or not activity.open_state then
        return skynet.retpack(false)
    end
    local service_addr = activity_service_map[act_id]
    if not service_addr then
        return skynet.retpack(false)
    end
    
    local ok,continue_time = R().hallsvr({key=uid}):call('.msg_handler', 'get_today_continue_time',uid)
    print("get_continue_time==========22",uid,ok,continue_time)
    local ret_data = skynet.call(service_addr,"lua", "take_task_act_award",uid,act_id,task_type,target_process,continue_time or 0)
    if not ret_data then
        return skynet.retpack(false)
    end

    return skynet.retpack(true)
end

function CMD.act_add_today_coins(uid,coins)
    print("act_add_today_coins============",uid,coins)
    local activities = global_configs.activity
    for act_id,activity in pairs(activities) do
        local service_addr = activity_service_map[act_id]
        if not service_addr then
            goto continue
        end

        if activity.ac_type ~= game_def.ACTIVITY_TYPE_RANK then --不是排行榜活动
            goto continue
        end

        local now = get_activity_time()
        skynet.send(service_addr,"lua", "act_add_today_coins",uid,coins,now)

        ::continue::
    end
end

function CMD.act_get_rank_list(rank_type)
    print("act_add_today_coins============",uid,coins)
    local ret_rank_list = {}
    local activities = global_configs.activity
    for act_id,activity in pairs(activities) do
        local service_addr = activity_service_map[act_id]
        if not service_addr then
            goto continue
        end

        if activity.ac_type ~= game_def.ACTIVITY_TYPE_RANK then --不是排行榜活动
            goto continue
        end

        local rank_list = skynet.call(service_addr,"lua", "get_rank_list",rank_type)
        ret_rank_list = rank_list or {}
        break

        ::continue::
    end

    skynet.retpack(ret_rank_list)
end


function CMD.get_web_rank_list(ac_type)
    local ret_rank_list = {}
    local activities = global_configs.activity
    for act_id,activity in pairs(activities) do
        local service_addr = activity_service_map[act_id]
        if not service_addr then
            goto continue
        end

        if activity.ac_type ~= ac_type then
            goto continue
        end

        local rank_list = skynet.call(service_addr,"lua", "web_get_rank_list",game_def.ACT_RANK_TYPE_CURR)
        ret_rank_list = rank_list or {}
        break

        ::continue::
    end

    skynet.retpack(ret_rank_list)
end

function CMD.web_add_rank_robot(data)
    local succ = false
    local activities = global_configs.activity
    print("web_add_rank_robot===========")
    for act_id,activity in pairs(activities) do
        local service_addr = activity_service_map[act_id]
        if not service_addr then
            goto continue
        end

        if activity.ac_type ~= (data.ac_type or 0) then
            goto continue
        end

        succ = true
        skynet.send(service_addr,"lua", "add_rank_robot",data)
        
        ::continue::
    end

    skynet.retpack(succ)
end

function CMD.web_add_robot_score(data)
    local succ = false
    local activities = global_configs.activity
    for act_id,activity in pairs(activities) do
        local service_addr = activity_service_map[act_id]
        if not service_addr then
            goto continue
        end

        if activity.ac_type ~= (data.ac_type or 0) then
            goto continue
        end

        succ = true
        skynet.send(service_addr,"lua", "add_rank_robot_score",data)

        ::continue::
    end

    skynet.retpack(succ)
end


function CMD.act_add_first_charge_process(uid,coins)
    if not check_player_first_charge(uid) then
        return
    end
    local activities = global_configs.activity
    for act_id,activity in pairs(activities) do
        local service_addr = activity_service_map[act_id]
        if not service_addr then
            goto continue
        end

        if activity.ac_type ~= game_def.ACTIVITY_TYPE_FIRST_CAHRGE then --不是首冲活动
            goto continue
        end

        skynet.send(service_addr,"lua", "act_add_first_charge_process",uid,coins)

        ::continue::
    end
end

function CMD.check_first_charge(uid,paid_amount)
    if not check_player_first_charge(uid) then
        return
    end

    local activities = global_configs.activity
    for act_id,activity in pairs(activities) do
        local service_addr = activity_service_map[act_id]
        if not service_addr then
            goto continue
        end

        if activity.ac_type ~= game_def.ACTIVITY_TYPE_FIRST_CAHRGE then --不是首冲活动
            goto continue
        end
        
        --如果充值不足首冲的设置金额，则任务玩家放弃充值奖励，设置首冲状态
        if paid_amount < activity.ac_content.charge_target then
            R().basesvr(1):send('.msg_handler','update_first_charge_status',uid,game_def.first_charge_has_taken)
            return
        end

        skynet.send(service_addr,"lua", "player_finish_first_charge",uid,paid_amount)

        ::continue::
    end
end


function CMD.set_gm_time(data)
    gm_time = data
    
    skynet.send(".rank_activity_award", "lua", "set_gm_time",gm_time)
    local activities = global_configs.activity
    for act_id,activity in pairs(activities) do
        local service_addr = activity_service_map[act_id]
        skynet.send(service_addr,"lua", "set_gm_time",gm_time)
    end

    skynet.retpack(true)
end

function CMD.get_curr_act_id_list()
    local act_id_list = {}
    for act_id,_ in pairs(activity_service_map) do
        table_insert(act_id_list,act_id)
    end

    skynet.retpack(act_id_list)
end
--------------拉新活动end------------------


function CMD.start()
	skynet.fork(check_activity_open_and_close)

	skynet.retpack(true)
end

function dispatch_cmd(session,source,action,...)
    print("dispatch_cmd================",action,...)
	if not CMD[action] then
    	errlog("unkown action", action)
    end

    CMD[action](...)
end

function start()
    skynet.start(function()
        skynet.dispatch("lua", function(session,source,action,...)
            dispatch_cmd(session,source,action,...)
        end)

        -- sharedata.query("global_configs")
        -- global_configs = setmetatable({},{
        --     __index = function(t,k) 
        --         return sharedata.query("global_configs")[k]
        --     end
        -- })  
        global_configs = setmetatable({},{
            __index = function(t,k) 
                --return sharedata.query("global_configs")[k]
                return sharedata.query(k)
            end
        })
        _G.global_configs = global_configs
    end)
end

_START(function()
    print('now this service is starting')
    init()
    start()
end)